﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

using OpGen.Compiler;
using OpGen.Compiler.Generator;
using OpGen.Compiler.Generator.CS;
using OpGen.Compiler.Generator.VB;
using OpGen.Compiler.Parser;

namespace OpGen
{
    class Program
    {
        static void Main(string[] args)
        {
            OpGenTitle();

            // Logger setzten
            Logger.MinMessageLevel = MessageTypeEnum.Trace;
            Logger.MaxMessageLevel = MessageTypeEnum.Fatal;

            var sourceFilename = "";
            var destinationFilename = "";
            var outLanguage = "CS";
            var useExtensions = false;

            var commandLine = Environment.CommandLine.Substring(Environment.CommandLine.LastIndexOf('\"') + 1).Trim();
            var pamaters = new LineSplitter(commandLine);

            // Parameter analysieren
            foreach (var para in pamaters)
            {
                // Kommandoszeichen?
                if (para.StartsWith("/") || para.StartsWith("-"))
                {
                    var seperator = para.IndexOf(':');
                    var value = seperator > -1 ? para.Substring(seperator+1) : "";
                    var command = seperator > -1 ? para.Substring(1, seperator - 1) : para.Substring(1);

                    switch (command.ToLower())
                    {
                        case "l":
                            switch (value.ToLower())
                            {
                                case "cs": outLanguage = "CS"; break;
                                case "vb": outLanguage = "VB"; break;
                                default: Console.WriteLine("Unkown Language '{0}'", value); break;
                            }
                            break;

                        case "ex":
                            useExtensions = true;break;

                        default:
                            Console.WriteLine("Unkown command '{0}'", command);
                            break;
                    }
                }
                else
                {
                    if (sourceFilename.Length == 0 & destinationFilename.Length == 0)
                    {
                        sourceFilename = para;
                        continue;
                    }

                    if (sourceFilename.Length > 0 & destinationFilename.Length == 0)
                    {
                        destinationFilename = para;
                        continue;
                    }
                }
            }

            // Dateipfade erzeugen
            if (sourceFilename.Length > 0)
            {
                var sourceFileInfo = new FileInfo(sourceFilename);

                if (destinationFilename.Length == 0)
                {
                    var fileExtension= outLanguage=="CS" ? "cs" : "vb";
                    destinationFilename = Path.Combine(sourceFileInfo.DirectoryName, string.Format("{0}.{1}", sourceFileInfo.FullName.Replace(sourceFileInfo.Extension, ""), fileExtension));
                }

                var destinationFileInfo = new FileInfo(destinationFilename);

                if (sourceFileInfo.Exists)
                {
                    var parser = new OpGenParser(sourceFileInfo);
                    CodeWriter targetGenerator = null;

                    parser.Project.UseExtension = useExtensions;

                    parser.Execute();

                    Console.ResetColor();
                    Console.WriteLine();
                    Console.WriteLine("--Errors---------------------------------------------------");
                    if (parser.ErrorList.Count == 0)
                        Console.WriteLine(" No Errors");

                    Console.WriteLine();

                    foreach (var item in parser.ErrorList)
                    {
                        Console.WriteLine("{0,4} {1,10} - {2}", item.Row, item.MessageType, item.Message);
                    }

                    if (!parser.ErrorList.HasException)
                    {
                        switch (outLanguage.ToLower())
                        {
                            case "cs":
                                targetGenerator = new CSCodeWriter(destinationFileInfo.Create());
                                break;
                            case "vb":
                                targetGenerator = new VBCodeWriter(destinationFileInfo.Create());
                                break;
                            default:
                                Console.WriteLine("Unkown Target Language.");
                                Environment.Exit(-1);
                                break;
                        }

                        Generator.GenerateCode(parser.Project, targetGenerator);
                    }
                }
                else
                {
                    Console.WriteLine("Source file not found");
                }
            }
            else
            {
                Console.WriteLine("No Sourcefile selected");
            }
            
#if DEBUG
            Console.ReadLine();
#endif
        }

        static void OpGenTitle()
        {

            Console.BackgroundColor = ConsoleColor.DarkRed;
            Console.ForegroundColor = ConsoleColor.White;
            Console.Write("OpGen Compiler Frontend {0}                                                 ", GetVersion());
            Console.Write("Copyright © 2012-2013  http://opgen.codeplex.com                                ");
            Console.WriteLine();
            Console.ResetColor();
            Console.WriteLine("Compiler : {0} BETA", OpGen.CompilerVersion.Version());
            Console.WriteLine();
        }

        static Version GetVersion()
        {
            var assembly = Assembly.GetEntryAssembly();

            if (assembly == null)
            {
                assembly = Assembly.GetCallingAssembly();
            }

            return assembly.GetName().Version;
        }
    }

}

